package com.xbongbong.paas.lowcode.impl;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.lowcode.DeveloperService;
import com.xbongbong.paas.lowcode.LowCodeActionSettingService;
import com.xbongbong.paas.model.LowCodeActionSettingModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.actionsetting.pojo.LowCodeActionListPojo;
import com.xbongbong.pro.actionsetting.pojo.LowCodeActionSettingPojo;
import com.xbongbong.pro.actionsetting.pojo.LowCodeFieldActionPojo;
import com.xbongbong.pro.actionsetting.pojo.dto.LowCodeActionSettingAddDTO;
import com.xbongbong.pro.actionsetting.pojo.dto.LowCodeActionSettingGetDTO;
import com.xbongbong.pro.actionsetting.pojo.dto.LowCodeActionSettingListDTO;
import com.xbongbong.pro.actionsetting.pojo.dto.LowCodeFieldActionGetDTO;
import com.xbongbong.pro.actionsetting.pojo.vo.LowCodeActionSettingAddVO;
import com.xbongbong.pro.actionsetting.pojo.vo.LowCodeActionSettingGetVO;
import com.xbongbong.pro.actionsetting.pojo.vo.LowCodeActionSettingListVO;
import com.xbongbong.pro.actionsetting.pojo.vo.LowCodeFieldActionGetVO;
import com.xbongbong.pro.domain.entity.LowCodeActionSettingEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.lowcode.FieldLowCodeActionEnum;
import com.xbongbong.pro.enums.lowcode.LowCodeActionEnum;
import com.xbongbong.pro.enums.lowcode.LowCodeActionTypeEnum;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/03/04 15:18
 */
@Service("lowCodeActionSettingService")
public class LowCodeActionSettingServiceImpl implements LowCodeActionSettingService {

    private static final Logger LOG = LoggerFactory.getLogger(LowCodeActionSettingServiceImpl.class);
    @Resource
    private LowCodeActionSettingModel lowCodeActionSettingModel;
    @Resource
    private DeveloperService developerService;
    @Resource
    private ProFormHelp proFormHelp;

    @Override
    public LowCodeFieldActionGetVO getFieldActionList(LowCodeFieldActionGetDTO lowCodeFieldActionGetDTO) throws XbbException {
        Map<String, List<LowCodeFieldActionPojo>> fieldAction = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
         for (FieldLowCodeActionEnum fieldLowCodeActionEnum: FieldLowCodeActionEnum.values()) {
             List<LowCodeActionEnum> lowCodeActionEnum = fieldLowCodeActionEnum.getActionList();
             List<LowCodeFieldActionPojo> list = new ArrayList<>();
             lowCodeActionEnum.forEach(item->{
                 LowCodeFieldActionPojo lowCodeFieldActionPojo = new LowCodeFieldActionPojo(item.getCode(), item.getAlias(), item.getMemo());
                 list.add(lowCodeFieldActionPojo);
             });
             if (Objects.isNull(fieldLowCodeActionEnum.getType())) {
                 fieldAction.put(fieldLowCodeActionEnum.getBelong(), list);
             } else {
                 fieldAction.put(fieldLowCodeActionEnum.getType().toString(), list);
             }
         }
         LowCodeFieldActionGetVO lowCodeFieldActionGetVO = new LowCodeFieldActionGetVO();
         lowCodeFieldActionGetVO.setFieldAction(fieldAction);
         return lowCodeFieldActionGetVO;
    }


    @Override
    public LowCodeActionSettingListVO fieldList(LowCodeActionSettingListDTO lowCodeActionSettingListDTO) throws XbbException {
        LowCodeActionSettingListVO lowCodeActionSettingListVO = new LowCodeActionSettingListVO();
        try {
            String corpid = lowCodeActionSettingListDTO.getCorpid();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.FORM_ID, lowCodeActionSettingListDTO.getFormId());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), lowCodeActionSettingListDTO.getBusinessType())) {
                param.put(StringConstant.BUSINESS_TYPE, lowCodeActionSettingListDTO.getBusinessType());
            }
            param.put("orderByStr", "sort ASC");
            List<LowCodeActionSettingEntity> lowCodeActionSettingList = lowCodeActionSettingModel.findEntitys(param);
            Map<String, List<LowCodeActionSettingEntity>> fieldLowCodeActionMap = new HashMap<>(lowCodeActionSettingList.size());
            lowCodeActionSettingList.forEach(item->{
               String attr = StringUtil.isEmpty(item.getAttr()) ? FieldLowCodeActionEnum.FORM.getBelong() : item.getAttr();
               if (fieldLowCodeActionMap.containsKey(attr)) {
                   List<LowCodeActionSettingEntity> list = fieldLowCodeActionMap.get(attr);
                   list.add(item);
                   fieldLowCodeActionMap.put(attr, list);
               } else {
                   List<LowCodeActionSettingEntity> list = new ArrayList<>();
                   list.add(item);
                   fieldLowCodeActionMap.put(item.getAttr(), list);
               }
            });

            Map<String, List<LowCodeActionListPojo>> resultLowCodeActionMap = new HashMap<>(fieldLowCodeActionMap.size());
            fieldLowCodeActionMap.forEach((key, value)->{
                Map<Integer, List<LowCodeActionSettingPojo>> lowCodeMap = getLowCodeActionMap(value);
                List<LowCodeActionListPojo> actionList = getActionList(lowCodeMap);
                resultLowCodeActionMap.put(key, actionList);
            });
            lowCodeActionSettingListVO.setActionList(resultLowCodeActionMap);
        }  catch (Exception e) {
            LOG.error("LowCodeActionSettingServiceImpl.list 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return lowCodeActionSettingListVO;
    }

    @Override
    public LowCodeActionSettingGetVO get(LowCodeActionSettingGetDTO lowCodeActionSettingGetDTO) throws XbbException {
        LowCodeActionSettingGetVO lowCodeActionSettingGetVO = new LowCodeActionSettingGetVO();
        try {
            String corpid = lowCodeActionSettingGetDTO.getCorpid();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.FORM_ID, lowCodeActionSettingGetDTO.getFormId());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("type", lowCodeActionSettingGetDTO.getType());
            if (Objects.equals(2, lowCodeActionSettingGetDTO.getType())) {
                param.put("attr", lowCodeActionSettingGetDTO.getAttr());
            }
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), lowCodeActionSettingGetDTO.getBusinessType())) {
                param.put(StringConstant.BUSINESS_TYPE, lowCodeActionSettingGetDTO.getBusinessType());
            }
            param.put("order by", "sort desc");
            List<LowCodeActionSettingEntity> lowCodeActionSettingList = lowCodeActionSettingModel.findEntitys(param);
            Map<Integer, List<LowCodeActionSettingPojo>> lowCodeMap = getLowCodeActionMap(lowCodeActionSettingList);
            List<LowCodeActionListPojo> actionList = getActionList(lowCodeMap);
            lowCodeActionSettingGetVO.setActionList(actionList);
        } catch (Exception e) {
            LOG.error("LowCodeActionSettingServiceImpl.get 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return lowCodeActionSettingGetVO;
    }

    @Override
    public LowCodeActionSettingAddVO add(LowCodeActionSettingAddDTO lowCodeActionSettingAddDTO) throws XbbException {
        LowCodeActionSettingAddVO lowCodeActionSettingAddVO = new LowCodeActionSettingAddVO();
        try {
            String corpid = lowCodeActionSettingAddDTO.getCorpid();
            Long formId = lowCodeActionSettingAddDTO.getFormId();
            Integer saasMark = lowCodeActionSettingAddDTO.getSaasMark();
            Integer businessType = lowCodeActionSettingAddDTO.getBusinessType();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.FORM_ID, lowCodeActionSettingAddDTO.getFormId());
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), lowCodeActionSettingAddDTO.getBusinessType())) {
                param.put(StringConstant.BUSINESS_TYPE, lowCodeActionSettingAddDTO.getBusinessType());
            }
            param.put("order by", "sort");
            List<LowCodeActionSettingEntity> settingList = lowCodeActionSettingModel.findEntitys(param);
            List<Long> deleteList = new ArrayList<>();
            for (LowCodeActionSettingEntity codeActionSettingEntity : settingList) {
                deleteList.add(codeActionSettingEntity.getId());
            }
            String userId = lowCodeActionSettingAddDTO.getUserId();
            List<LowCodeActionSettingEntity> addList = new ArrayList<>();
            List<LowCodeActionSettingEntity> updateList = new ArrayList<>();
            List<LowCodeActionSettingPojo> lowCodeActionSettingList = lowCodeActionSettingAddDTO.getLowCodeActionSettingList();
            Set<Long> updateIdSet = new HashSet<>();

            lowCodeActionSettingList.forEach(item->{
                Long serviceId = 0L;
                if (Objects.equals(LowCodeActionTypeEnum.API_SERVICE.getCode(), item.getActionType()) || Objects.equals(LowCodeActionTypeEnum.INITIATE_REQUEST.getCode(), item.getActionType())) {
                    serviceId = item.getParam().getLong("serviceId");
                }
                if (Objects.isNull(item.getId())) {
                    long now = DateTimeUtil.getInt();
                    LowCodeActionSettingEntity lowCodeActionSettingEntity = new LowCodeActionSettingEntity(corpid, formId, saasMark, businessType, item.getType(), item.getTriggerTiming(),
                            item.getActionType(), item.getAttr(), item.getFieldType(), serviceId,
                            JSON.toJSONString(item.getParam()), item.getSort(), userId, now, now);
                    addList.add(lowCodeActionSettingEntity);
                } else {
                    long now = DateTimeUtil.getInt();
                    LowCodeActionSettingEntity lowCodeActionSettingEntity = new LowCodeActionSettingEntity(item.getId(), item.getType(), item.getTriggerTiming(),
                            item.getActionType(), item.getAttr(), item.getFieldType(), serviceId,
                            JSON.toJSONString(item.getParam()), item.getSort(),  now);
                    updateList.add(lowCodeActionSettingEntity);
                    updateIdSet.add(item.getId());
                }
            });
            deleteList.removeAll(updateIdSet);

            if (CollectionsUtil.isNotEmpty(addList)) {
                lowCodeActionSettingModel.addBatch(addList);
            }
            if (CollectionsUtil.isNotEmpty(updateList)) {
                lowCodeActionSettingModel.updateBatch(updateList, corpid);
            }
            if (CollectionsUtil.isNotEmpty(deleteList)) {
                // 删除的逻辑
                lowCodeActionSettingModel.deleteBatch(deleteList, corpid);
            }
        } catch (Exception e) {
            LOG.error("LowCodeActionSettingServiceImpl.add 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return lowCodeActionSettingAddVO;
    }

    /**
     * 将动作归类转化为list
     * @param lowCodeMap
     * @return
     */
    private List<LowCodeActionListPojo> getActionList(Map<Integer, List<LowCodeActionSettingPojo>> lowCodeMap) {
        List<LowCodeActionListPojo> actionList = new ArrayList<>();
        for (LowCodeActionEnum lowCodeActionEnum: LowCodeActionEnum.values()) {
            if (lowCodeMap.containsKey(lowCodeActionEnum.getCode())) {
                LowCodeActionListPojo lowCodeActionListPojo = new LowCodeActionListPojo(lowCodeActionEnum.getMemo(), lowCodeActionEnum.getCode(), lowCodeMap.get(lowCodeActionEnum.getCode()));
                actionList.add(lowCodeActionListPojo);
            }
        }
        return actionList;
    }

    /**
     * 将相同触发动作的动作设置进行归类
     * @param lowCodeActionSettingList
     * @return
     */
    private Map<Integer, List<LowCodeActionSettingPojo>> getLowCodeActionMap(List<LowCodeActionSettingEntity> lowCodeActionSettingList) {
        Map<Integer, List<LowCodeActionSettingPojo>> lowCodeMap = new HashMap<>(lowCodeActionSettingList.size());
        if (CollectionsUtil.isEmpty(lowCodeActionSettingList)) {
            return lowCodeMap;
        }
        lowCodeActionSettingList.forEach(item->{
            if (lowCodeMap.containsKey(item.getTriggerTiming())) {
                List<LowCodeActionSettingPojo> list = lowCodeMap.get(item.getTriggerTiming());
                LowCodeActionSettingPojo lowCodeActionSettingPojo = new LowCodeActionSettingPojo(item.getId(), item.getType(), item.getTriggerTiming(), item.getActionType(),
                        item.getAttr(), item.getFieldType(), JSON.parseObject(item.getParam()), item.getSort());
                list.add(lowCodeActionSettingPojo);
                lowCodeMap.put(item.getTriggerTiming(), list);
            } else {
                List<LowCodeActionSettingPojo> list = new ArrayList<>();
                LowCodeActionSettingPojo lowCodeActionSettingPojo = new LowCodeActionSettingPojo(item.getId(), item.getType(), item.getTriggerTiming(), item.getActionType(),
                        item.getAttr(), item.getFieldType(), JSON.parseObject(item.getParam()), item.getSort());
                list.add(lowCodeActionSettingPojo);
                lowCodeMap.put(item.getTriggerTiming(), list);
            }
        });
        return lowCodeMap;
    }
}
